#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <expat.h>
#include <fstream>
#include <exception>

#include "factory_method.h"

using namespace std;

static size_t wordscount_ = 0;

size_t GetWordsCount(string text)
{
	int counter = -1;
	bool b = false;

	for(size_t i = 0; text[i] != '\0'; ++i)
	{
		if(text[0] == '\n')
			break;
		if(text[i] != ' ' && !b){
			b = true;
			++counter;
		}
		if(text[i] == ' ' && b)
			++counter;
	}
	return counter + 1;
}

void start(void *data, const char *el, const char **attr)
{
	for (size_t i = 0; attr[i]; i += 2)
	{
	  wordscount_ += 2;
	  cout << attr[i] << " = " << attr[i + 1] << "\n";
	}
}

void end(void *data, const char *el)
{
}

void handle_data(void *data, const char* content, int length)
{
	char *lastContent_;
	char *tmp = new char[length];
	strncpy(tmp, content, length);

	tmp[length] = '\0';

	data = (void *)tmp;
	lastContent_ = tmp;

	//if(lastContent_[0] != '\n')
	//	cout << lastContent_ << "\n";

	wordscount_ += GetWordsCount(lastContent_);
}

string GetFileContent(string filepath)
{
	ifstream inputfile;
    inputfile.open(filepath.c_str());

    if(inputfile.fail())
    	throw "Unable to open file";


    string data((istreambuf_iterator<char>(inputfile)), (istreambuf_iterator<char>()));
    inputfile.close();
	return data;
}

size_t TxtFile :: getWordsCount(string data)
{
    return  GetWordsCount(data);
}

size_t XmlFile :: getWordsCount(string data)
{
    wordscount_ = 0;
    XML_Parser parser = XML_ParserCreate(NULL);

    XML_SetElementHandler(parser, start, end);
    XML_SetCharacterDataHandler(parser, handle_data);


    if(XML_Parse(parser, data.c_str(), data.length(), XML_TRUE) == XML_STATUS_ERROR)
    {
    	string exception =  XML_ErrorString(XML_GetErrorCode(parser));
    	throw exception;
    }


    XML_ParserFree(parser);

    return wordscount_;
}

int main() {
	const size_t count = 2;
    Creator* creators[count] = { new ConcreteCreatorA(), new ConcreteCreatorB() };

	try
	{
        Product* product1 = creators[0]->factoryMethod();
        cout << "< Count of words in this file: > " << product1 -> getWordsCount(GetFileContent("src/i.txt")) << endl;
        delete product1;

        Product* product2 = creators[1]->factoryMethod();
        cout << "< Count of words in this file: > " << product2 -> getWordsCount(GetFileContent("src/i.xml")) << endl;
        delete product2;
	}
	catch(string e)
	{
	     cout << e;
	}
	catch(...)
	{
		cout << "Error";
	}

    for (size_t i = 0; i < count; i++)
        delete creators[i];

        return 0;
}
